<template>
  <Card :bordered="false" class="calendarCard" :loading="loading.state.value">
    <div class="calendar" ref="calendarRef">
      <div class="month" v-for="(month, index) in months" :key="index">
        <div class="title">
          <TypographyText strong type="secondary">
            {{ month.title }}
          </TypographyText>
        </div>
        <div class="days">
          <template v-for="(day, i) in month.days" :key="i">
            <Tooltip>
              <template #title>
                <template v-if="!renderDay(day)">{{ day }}</template>
                <span v-else>
                  {{ day }}
                  <Divider type="vertical" />
                  <strong>{{ renderDay(day) }}</strong>
                </span>
              </template>
              <div
                class="day"
                :class="renderDay(day) ? 'active' : ''"
                :style="
                  renderDay(day)
                    ? {
                        filter: `brightness(${renderDay(day) * 0.5})`,
                      }
                    : {}
                "
              ></div>
            </Tooltip>
          </template>
        </div>
      </div>
    </div>
  </Card>
</template>

<script setup lang="ts">
import { computed, onBeforeMount, onMounted, ref } from 'vue'
import { Card, TypographyText, Tooltip, Divider } from 'ant-design-vue'
import dayjs from 'dayjs'
import { WheelEventHandler } from 'ant-design-vue/lib/_util/EventInterface'
import { useLoading } from '@/handcer'
import { ArticleCalendarItem, getArticleCalendar } from '@/store/system'

const CALENDAR_DAY_FORMAT = 'YYYY-MM-DD'
const CALENDAR_MONTH_FORMAT = 'YYYY/MM'

const getMonthFullDays = (month: dayjs.Dayjs) => {
  const daysCount = month.daysInMonth()
  return Array.from({ length: daysCount }).map((d, i) => {
    return month.date(i + 1).format(CALENDAR_DAY_FORMAT)
  })
}

const calendarRef = ref<HTMLDivElement>()
const handleCalendarScroll: WheelEventHandler = (event: WheelEvent) => {
  event.preventDefault()
  if (calendarRef.value) {
    if (event.deltaY > 0) {
      calendarRef.value.scrollLeft += calendarRef.value.clientWidth / 2
    } else {
      calendarRef.value.scrollLeft -= calendarRef.value.clientWidth / 2
    }
  }
}

const loading = useLoading()
const articleCalendar = ref<Array<ArticleCalendarItem>>([])
const fetchArticleCalendar = () => {
  return loading.promise(getArticleCalendar()).then((result) => {
    articleCalendar.value = result
  })
}

const renderDay = (date: string): number => {
  const count = articleCalendar.value.find((ac) => ac.date === date)?.count || 0

  return count
}

// 当前月份 | 日期
const currentMonth = computed(() => {
  const today = dayjs()
  const days = Array.from({ length: today.date() }).map((_, i) => {
    return today.date(i + 1).format(CALENDAR_DAY_FORMAT)
  })
  return {
    title: today.format(CALENDAR_MONTH_FORMAT),
    days,
  }
})

const months = computed<{ title: string; days: string[] }[]>(() => {
  const firstArticleDate = articleCalendar.value[0]?.date

  if (!firstArticleDate) {
    return []
  }

  const firstDay = dayjs(firstArticleDate)
  const today = dayjs()

  // 前一月
  let months = Math.ceil(today.diff(firstDay, 'day') / 30)

  if (months < 1) {
    months += 1
  }

  const monthsDays = Array.from({ length: months }).map((_, i) => {
    const month = today.clone().subtract(i + 1, 'month')
    const days = getMonthFullDays(month)
    return {
      title: month.format(CALENDAR_MONTH_FORMAT),
      days,
    }
  })

  return [...monthsDays.reverse(), currentMonth.value]
})

onMounted(() => {
  fetchArticleCalendar().then(() => {
    setTimeout(() => {
      if (calendarRef.value) {
        calendarRef.value.scrollLeft = calendarRef.value.scrollWidth
        calendarRef.value.addEventListener('wheel', handleCalendarScroll as any)
      }
    }, 0)
  })
})

onBeforeMount(() => {
  calendarRef.value?.removeEventListener('wheel', handleCalendarScroll as any)
})
</script>

<style lang="less" scoped>
.calendarCard {
  .calendar {
    display: flex;
    padding-bottom: @gap;
    overflow-y: hidden;
    overflow-x: scroll;
    scroll-snap-type: x mandatory;
    // scroll-behavior: smooth;

    .month {
      scroll-snap-align: start;
      margin-right: @gap * 1.5;
      &:last-child {
        margin-right: 0;
      }

      .title {
        margin-bottom: @gap;
        user-select: none;
      }

      .days {
        width: auto;
        display: grid;
        grid-template-rows: repeat(7, 1fr);
        grid-auto-flow: column;
        grid-auto-columns: min-content;
        grid-gap: 5px;

        .day {
          width: 10px;
          height: 10px;
          background-color: @module-bg-lighter;
          &.active {
            background-color: @primary;
          }
        }
      }
    }
  }
}
</style>
